package cn.edu.jlu.grid.vjm;

import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Vector;
import java.util.logging.Logger;
import org.globus.util.deactivator.Deactivator;

public class VJMCenter {
	private static VJMCenter inst = null;
	private HashMap<Integer, VJMPIJob> registeredMPIJobs;
	private VJMMessageCenter msgCenter;
	private Logger logger = Logger.getLogger(VJMCenter.class.getName());
	
	private VJMCenter() {
		registeredMPIJobs = new HashMap<Integer, VJMPIJob>();
		msgCenter = new VJMMessageCenter();
		logger.info("VJMCenter start and listen at port: " + msgCenter.getPort());
		
		VJobPool.init();
	}
	
	public static void init() {
		if(inst == null) inst = new VJMCenter();
	}
	
	/*
	public static void release() throws RunningMPIJobsExistsException {
		if(getInstance().getRegisteredMPIJobsCount() != 0) {
			throw new RunningMPIJobsExistsException();
		}
		getInstance().msgCenter.stop();
	}
	*/
	public static void release() {
		VJobPool.getInstance().release();
		getInstance().msgCenter.stop();
		Deactivator.deactivateAll();
	}
	
	public static VJMCenter getInstance() {
		if(inst == null)
			init();
		return inst;
	}
	
	public InetAddress getVJCAddress() {
		//return msgCenter.getAddress(); // this will be 0.0.0.0
		//return InetAddress.getLocalHost(); // must surround with try/catch
		InetAddress addr = null;
		try { addr = InetAddress.getLocalHost(); } catch(Exception e){}
		return addr;
	}
	public int getVJCPort() {
		return msgCenter.getPort();
	}
	public int getRegisteredMPIJobsCount() {
		return registeredMPIJobs.size();
	}
	public Collection<VJMPIJob> getRegisteredMPIJobs() {
		return registeredMPIJobs.values();
	}

	public VJMPIJob getMPIJobByID(int id) {
		return registeredMPIJobs.get(id);
	}
	public void registerMPIJob(VJMPIJob job) {
		registeredMPIJobs.put(job.getID(), job);
	}
	
	private class VJMMessageCenter implements Runnable {
		private Thread t = new Thread(this);
		private ServerSocket server;
		private int port;
		
		public VJMMessageCenter() {
			try {
				server = new ServerSocket(0);
			} catch (IOException e) { e.printStackTrace(); }
			
			port = server.getLocalPort();
			t.start();
		}
		
		public InetAddress getAddress() {
			return server.getInetAddress();
		}
		public int getPort() { return port; }
		
		public void stop() { 
			t.stop();
			if(!server.isClosed()) {
				try { server.close(); } catch (Exception e) {}
			}
		}
		
		public void run() {
			while(true) {
				try {
					Socket conn = server.accept();
					new Thread(new VJMMessageProcessor(conn)).start();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}
